package com.betterjr.modules.application.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

import com.betterjr.common.service.BaseService;
import com.betterjr.common.utils.BTAssert;
import com.betterjr.common.utils.Collections3;
import com.betterjr.common.utils.QueryTermBuilder;
import com.betterjr.common.utils.TreeUtilCommon;
import com.betterjr.common.utils.UserUtils;
import com.betterjr.mapper.pagehelper.Page;
import com.betterjr.modules.application.IAmsMenuInfoUndercarriage;
import com.betterjr.modules.application.dao.AmsMenuInfoMapper;
import com.betterjr.modules.application.data.AmsMenuInfoConstantCollections;
import com.betterjr.modules.application.data.ApplicationConstantCollections;
import com.betterjr.modules.application.entity.AmsMenuInfo;
import com.betterjr.modules.application.entity.AmsMenuResourceRelation;
import com.betterjr.modules.application.entity.AmsResource;
import com.betterjr.modules.application.entity.Application;
import com.betterjr.modules.customer.service.CustMajorService;

/**
 * 
 * @ClassName: AmsMenuInfoService 
 * @Description: 菜单服务 
 * @author xuyp
 * @date 2017年11月17日 下午6:05:08 
 *
 */
@Service
public class AmsMenuInfoService extends BaseService<AmsMenuInfoMapper, AmsMenuInfo> implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Autowired
    private ApplicationService applicationService;

    @Autowired
    private AmsMenuResourceRelationService relationService;

    @Autowired
    private ApplicationGroupService groupService;

    @Autowired
    private CustMajorService custMajorService;

    /**
     * 
     * @Title: saveAddMenuInfo 
     * @Description: 菜单新增 
     * @param anParentId
     * @param anMenuName
     * @param anApplicationId
     * @return AmsMenuInfo
     * @throws 
     * @author xuyp
     * @date 2017年11月17日 下午4:29:18
     */
    public AmsMenuInfo saveAddMenuInfo(Long anParentId, String anMenuName, Long anApplicationId) {

        BTAssert.notNull(anParentId, "数据为空,操作失败");
        BTAssert.notNull(anApplicationId, "数据为空,操作失败");
        BTAssert.isTrue(StringUtils.isNotBlank(anMenuName), "菜单为空，操作失败");
        Application application = applicationService.selectByPrimaryKey(anApplicationId);
        BTAssert.notNull(application, "数据为空,操作失败");

        AmsMenuInfo menuInfo = new AmsMenuInfo();
        menuInfo.saveAddValue();
        menuInfo.setRuleList(application.getRuleList());
        menuInfo.setApplicationId(anApplicationId);
        menuInfo.setParentId(anParentId);
        menuInfo.setMenuName(anMenuName);
        // 修改父节点叶子节点
        if (!anParentId.equals(0L)) {

            AmsMenuInfo parentMenuInfo = findEffectiveMenuInfo(anParentId);
            if (AmsMenuInfoConstantCollections.AMSMENUINFO_ENDNODE_ISEND.equals(parentMenuInfo.getEndNode())) {
                parentMenuInfo.setEndNode(AmsMenuInfoConstantCollections.AMSMENUINFO_ENDNODE_NOTEND);
                this.updateByPrimaryKeySelective(parentMenuInfo);
            }
        }

        this.insertSelective(menuInfo);
        return menuInfo;

    }

    /**
     * 
     * @Title: saveUpdateMenuInfo 
     * @Description: 修改菜单信息
     * @param anMenuInfo
     * @param anRourceIds
     * @return AmsMenuInfo
     * @throws 
     * @author xuyp
     * @date 2017年11月17日 下午5:16:36
     */
    public AmsMenuInfo saveUpdateMenuInfo(AmsMenuInfo anMenuInfo, String anRourceIds) {

        BTAssert.notNull(anMenuInfo, "数据为空,操作失败");
        BTAssert.notNull(anMenuInfo.getId(), "数据为空,操作失败");
        BTAssert.notNull(anMenuInfo.getApplicationId(), "数据为空,操作失败");
        BTAssert.notNull(anMenuInfo.getParentId(), "数据为空,操作失败");

        AmsMenuInfo oldMenuInfo = findEffectiveMenuInfo(anMenuInfo.getId());
        BTAssert.notNull(oldMenuInfo, "数据为空,操作失败");
        anMenuInfo.setOrderMenu(oldMenuInfo.getOrderMenu());
        if (!oldMenuInfo.getApplicationId().equals(anMenuInfo.getApplicationId())
                || StringUtils.isBlank(anMenuInfo.getRuleList())) {

            Application application = applicationService.selectByPrimaryKey(anMenuInfo.getApplicationId());
            BTAssert.notNull(application, "数据为空,操作失败");
            anMenuInfo.setRuleList(application.getRuleList());
        }

        if (!oldMenuInfo.getParentId().equals(anMenuInfo.getParentId())) {

            // 修改原菜单节点的叶子节点
            saveUpdateMenuInfoEndNodeById(oldMenuInfo.getParentId());
            // 修改新父节点叶子节点状态
            saveUpdateMenuInfoEndNodeById(anMenuInfo.getParentId());
        }

        this.updateByPrimaryKeySelective(anMenuInfo);

        // 修改资源与菜单中间表
        List<AmsMenuResourceRelation> lists = relationService
                .updateRelationsByMenuinfoIdWithResourceIds(anMenuInfo.getId(), anRourceIds);

        return anMenuInfo;

    }

    /**
     * 
     * @Title: saveUpdateRuleListByApplicaitonId 
     * @Description: 更新应用对应的角色信息(当应用修改的了角色的时候)
     * @param anApplicaitonid
     * @return List<AmsMenuInfo>
     * @throws 
     * @author xuyp
     * @date 2017年11月17日 下午5:24:42
     */
    @SuppressWarnings("unchecked")
    public List<AmsMenuInfo> saveUpdateRuleListByApplicaitonId(Long anApplicaitonid, String anRuleList) {

        BTAssert.notNull(anApplicaitonid, "数据为空,操作失败");
        Application application = applicationService.selectByPrimaryKey(anApplicaitonid);
        BTAssert.notNull(application, "数据为空,操作失败");

        Map<String, Object> map = QueryTermBuilder.newInstance().put("applicationId", anApplicaitonid)
                .put("businStatus", AmsMenuInfoConstantCollections.AMSMENUINFO_BUSINSTATUS_EFFECTIVED).build();
        List<AmsMenuInfo> list = this.selectByProperty(map);
        for (AmsMenuInfo amsMenuInfo : list) {
            if (!amsMenuInfo.getRuleList().equals(anRuleList)) {

                amsMenuInfo.setRuleList(anRuleList);
                this.updateByPrimaryKeySelective(amsMenuInfo);
            }

        }

        return list;

    }

    /**
     * 
     * @Title: findMenuInfoDetail 
     * @Description: 查询单条菜单的详细信息 
     * @param anId
     * @param anResourceModelType  1 返回资源封装后的信息
     * @return 返回菜单对象
     * @throws 
     * @author xuyp
     * @date 2017年11月20日 上午11:42:14
     */
    public AmsMenuInfo findMenuInfoDetail(Long anId, String anResourceModelType) {

        BTAssert.notNull(anId, "数据为空,操作失败");
        AmsMenuInfo menuInfo = this.selectByPrimaryKey(anId);
        BTAssert.notNull(menuInfo, "数据为空,操作失败");
        List<AmsResource> resourceList = relationService.selectResourcesByMenuInfoId(anId);
        menuInfo.setResourceList(resourceList);

        if (StringUtils.isNoneBlank(anResourceModelType) && !Collections3.isEmpty(resourceList)
                && "1".equals(anResourceModelType)) {
            // 将资源列表转成资源扩展列表
            for (AmsResource amsResource : resourceList) {
                menuInfo.getResourceExtendList().add(amsResource.conventToExtend());
            }

        }

        return menuInfo;
    }

    /**
     * 
     * @Title: selectMenuListByApplicaitonid 
     * @Description: 根据应用id查询所有的菜单列表 
     * @param anApplicaitonId  应用id
     * @param anFlag   是否查询资源信息  1 查询    9 不查询
     * @return 菜单列表
     * @throws 
     * @author xuyp
     * @date 2017年11月20日 上午11:52:00
     */
    @SuppressWarnings("unchecked")
    public List<AmsMenuInfo> selectMenuListByApplicaitonid(Long anApplicaitonId, String anFlag) {

        List<AmsMenuInfo> list = queryMenuListByApplicationIdNoSort(anApplicaitonId, anFlag);

        // 封装子菜单
        // 构建树
        List<AmsMenuInfo> treeList = new ArrayList<AmsMenuInfo>();
        try {
            treeList = TreeUtilCommon.buildTree(list, "com.betterjr.modules.application.entity.AmsMenuInfo", "id",
                    "parentId", "childrens");
        }
        catch (Exception e) {
            logger.info("构建菜单树失败！" + e.getMessage());
        }

        return Collections3.isEmpty(treeList) ? list : treeList;

    }

    public Page<AmsMenuInfo> selectMenuPageByApplicaitonid(Long anApplicaitonId, String anFlag) {

        List<AmsMenuInfo> list = queryMenuListByApplicationIdNoSort(anApplicaitonId, anFlag);

        Page<AmsMenuInfo> page = new Page<>();
        page.setTotal(Collections3.isEmpty(list) ? 0 : list.size());
        page.addAll(selectMenuListByApplicaitonid(anApplicaitonId, anFlag));

        return page;

    }

    /**
     * 
     * @Title: queryCurrentUserAllMenuInfo 
     * @Description: 查询当前用户所有的菜单信息 
     * @param anBusinStatus  状态 1未生效 2已生效
     * @param anFlag 是否查询资源信息  1 查询    9 不查询
     * @return 查询当前用户所有的菜单信息 
     * @throws 
     * @author xuyp
     * @date 2017年12月12日 下午5:04:25
     */
    public List<AmsMenuInfo> queryCurrentUserAllMenuInfo(String anBusinStatus, String anFlag) {

        List<AmsMenuInfo> menuList = new ArrayList<>();

        // 查询当前用户应用列表
        List<Application> queryApplications = groupService.queryApplications(null, anBusinStatus);

        for (Application application : queryApplications) {
            menuList.addAll(queryMenuListByApplicationIdNoSort(application.getId(), anFlag));
        }

        return menuList;

    }

    /*
     * 删除菜单信息 并且同步菜单下架
     */
    public AmsMenuInfo saveDeleteMenuInfoById(Long anId) {

        BTAssert.notNull(anId, "数据为空,操作失败");
        BTAssert.isTrue(checkCurrentUserPriviledge(), "你没有当前操作的权限");
        AmsMenuInfo menuInfo = this.selectByPrimaryKey(anId);
        BTAssert.notNull(menuInfo, "数据为空,操作失败");

        if (AmsMenuInfoConstantCollections.AMSMENUINFO_BUSINSTATUS_NOEFFECTIVED.equals(menuInfo.getBusinStatus())) {

            BTAssert.notNull(null, "当前菜单已经失效,操作失败");
        }

        menuInfo.setBusinStatus(AmsMenuInfoConstantCollections.AMSMENUINFO_BUSINSTATUS_NOEFFECTIVED);

        this.updateByPrimaryKeySelective(menuInfo);

        // 同步下载当前菜单信息
        saveUpdateMenuInfoByInterfaces(anId);

        return menuInfo;

    }

    private boolean checkCurrentUserPriviledge() {

        String ruleList = UserUtils.getOperatorInfo().getRuleList();
        // System.out.println(ruleList);
        // 得到平台操作机构
        String operOrg = custMajorService.findPlatCustMajorDetail().getOperOrg();
        // 如果是管理员并且是平台 查询所有的应用
        if (ApplicationConstantCollections.APPLICATION_OPERATOR_ADMIN.equals(ruleList)
                && UserUtils.getOperatorInfo().getOperOrg().equals(operOrg)) {
            return true;
        }

        return false;

    }

    /**
     * 
     * @Title: saveUpdateMenuInfoByInterfaces 
     * @Description: 同步更新菜单下架 
     * @param anId 同步更新菜单下架
     * @throws 
     * @author xuyp
     * @date 2017年12月21日 下午3:13:30
     */
    private void saveUpdateMenuInfoByInterfaces(Long anId) {

        String[] namesForType = applicationContext.getBeanNamesForType(IAmsMenuInfoUndercarriage.class);
        // List<IAmsMenuInfoUndercarriage> lists = new ArrayList<>(namesForType.length);
        for (String string : namesForType) {
            IAmsMenuInfoUndercarriage bean = (IAmsMenuInfoUndercarriage) applicationContext.getBean(string);
            bean.saveUndercarriageMenuInfo(anId);
        }

    }

    /**
     * 
     * @Title: queryMenuListByApplicationIdNoSort 
     * @Description: 根据应用id查询当前应用下所有的菜单 
     * @param anApplicaitonId
     * @param anFlag  是否查询资源信息  1 查询    9 不查询
     * @return 根据应用id查询当前应用下所有的菜单
     * @throws 
     * @author xuyp
     * @date 2017年12月12日 下午5:00:03
     */
    @SuppressWarnings("unchecked")
    private List<AmsMenuInfo> queryMenuListByApplicationIdNoSort(Long anApplicaitonId, String anFlag) {
        BTAssert.notNull(anApplicaitonId, "数据为空,操作失败");
        Map<String, Object> map = QueryTermBuilder.newInstance().put("applicationId", anApplicaitonId)
                .put("businStatus", AmsMenuInfoConstantCollections.AMSMENUINFO_BUSINSTATUS_EFFECTIVED).build();
        List<AmsMenuInfo> list = this.selectByProperty(map, "orderMenu asc, id asc");
        if (Collections3.isEmpty(list)) {
            return new ArrayList<AmsMenuInfo>();
        }

        // 是否封装资源表信息
        if (anFlag.equals(AmsMenuInfoConstantCollections.AMSMENUINFO_METHOD_QUERY_RESOURCEDETAIL_OK)) {
            for (AmsMenuInfo amsMenuInfo : list) {
                amsMenuInfo.setResourceList(relationService.selectResourcesByMenuInfoId(amsMenuInfo.getId()));
            }

        }
        return list;
    }

    /**
     * 
     * @Title: packMenuInfoChildrens 
     * @Description: 将父菜单的所有子菜单封装进父菜单中 
     * @param anMenuInfo
     * @param anSourceMenuInfo
     * @return 
     * @throws 
     * @author xuyp
     * @date 2017年11月22日 上午11:55:35
     */
    private AmsMenuInfo packMenuInfoChildrens(AmsMenuInfo anMenuInfo, List<AmsMenuInfo> anSourceMenuInfo) {

        BTAssert.notNull(anMenuInfo, "数据为空,操作失败");

        if (!Collections3.isEmpty(anSourceMenuInfo)
                && !AmsMenuInfoConstantCollections.AMSMENUINFO_ENDNODE_ISEND.equals(anMenuInfo.getEndNode())) {
            try {
                anMenuInfo = TreeUtilCommon.getNodeById(anSourceMenuInfo, anMenuInfo.getId(),
                        "com.betterjr.modules.application.entity.AmsMenuInfo", "id", "parentId", "childrens");
            }
            catch (Exception e) {

                e.printStackTrace();
            }
        }
        return anMenuInfo;
    }

    /**
     * 
     * @Title: saveUpdateMenuInfoEndNodeById 
     * @Description: 查询菜单的子菜单，然后修改是否是叶子节点
     * @param parentId 主键id
     * @throws 
     * @author xuyp
     * @date 2017年11月17日 下午5:09:27
     */

    private AmsMenuInfo saveUpdateMenuInfoEndNodeById(Long anId) {

        if (!anId.equals(0L)) {

            @SuppressWarnings("unchecked")
            Map<String, Object> map = QueryTermBuilder.newInstance().put("parentId", anId)
                    .put("businStatus", AmsMenuInfoConstantCollections.AMSMENUINFO_BUSINSTATUS_EFFECTIVED).build();
            List<AmsMenuInfo> list = this.selectByProperty(map);
            if (Collections3.isEmpty(list)) {
                AmsMenuInfo menuInfo = this.findEffectiveMenuInfo(anId);
                menuInfo.setEndNode(AmsMenuInfoConstantCollections.AMSMENUINFO_ENDNODE_NOTEND);
                this.updateByPrimaryKeySelective(menuInfo);
                return menuInfo;
            }
        }

        return null;

    }

    /**
     * 
     * @Title: findEffectiveMenuInfo 
     * @Description: 查询生效的菜单信息
     * @param anId  主键id
     * @return AmsMenuInfo
     * @throws 
     * @author xuyp
     * @date 2017年11月17日 下午5:17:56
     */
    private AmsMenuInfo findEffectiveMenuInfo(Long anId) {

        BTAssert.notNull(anId, "数据为空,操作失败");
        AmsMenuInfo menuInfo = this.selectByPrimaryKey(anId);
        BTAssert.notNull(menuInfo, "数据为空,操作失败");
        BTAssert.isTrue(
                AmsMenuInfoConstantCollections.AMSMENUINFO_BUSINSTATUS_EFFECTIVED.equals(menuInfo.getBusinStatus()),
                "当前菜单已经不可用");
        return menuInfo;

    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

        this.applicationContext = applicationContext;
    }

}
